package org.longteng.security.handle;

import com.auth0.jwt.exceptions.JWTVerificationException;
import org.longteng.core.annotation.AuthIgnore;
import org.longteng.security.Constants;
import org.longteng.security.service.JwtTokenService;
import org.longteng.security.vo.AuthorizationTokenVo;
import org.longteng.core.utils.JSONObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.security.auth.message.AuthException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * 拦截器去获取token并验证token, Bean方式加到WebMvcConfigurer.addInterceptors
 * @author hymn.com
 * @date 2022/12/07 10:00:00
 */
@Slf4j
public class AuthorizationInterceptor implements HandlerInterceptor {
    @Autowired
    private JwtTokenService jwtTokenService;

    /**
     * 拦截器去获取token
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 如果不是映射到方法直接通过
        if( !(handler instanceof HandlerMethod)) {
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod)handler;
        Method method = handlerMethod.getMethod();
        AuthIgnore annotation = ((HandlerMethod) handler).getMethodAnnotation(AuthIgnore.class);
        //如果有@AuthIgnore注解，则不验证token
        if(annotation != null && annotation.required()){
            return true;
        }

        //获取用户凭证
        String token = request.getHeader(Constants.TOKEN_HEADER_AUTHORIZATION);
        if(StringUtils.isBlank(token)){
            token = request.getParameter(Constants.TOKEN_HEADER_AUTHORIZATION);
        }
        if(StringUtils.isBlank(token)){
            Object obj = request.getAttribute(Constants.TOKEN_HEADER_AUTHORIZATION);
            if(null != obj){
                token = obj.toString();
            }
        }

        //token凭证为空
        if(StringUtils.isBlank(token)){
            throw new AuthException(Constants.TOKEN_HEADER_AUTHORIZATION + "不能为空");
        }

        log.debug("拦截开始验证取得token.");
        AuthorizationTokenVo authorizationTokenVo = JSONObjectUtil.parseObject(token, AuthorizationTokenVo.class );
        if (authorizationTokenVo == null) {
            throw new AuthException(Constants.TOKEN_HEADER_AUTHORIZATION + "内token内容错误.");
        }

        try {
            jwtTokenService.verify(authorizationTokenVo.getToken(), authorizationTokenVo); // 验证token
        }catch (JWTVerificationException e) {
            throw new AuthException("token解析错误.");
        }

        return true;
    }
}
